﻿using System;
using System.ComponentModel;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Threading;
using System.Windows.Forms;
using NLog;
using Raytracer.Configurations;
using Raytracer.Generator;
using RaytracerLib;
using RaytracerLib.MathLib;
using TomanuExtensions;
using System.Collections.Generic;
using RaytracerLib.Materials;
using RaytracerLib.RenderableObjects;
using RaytracerLib.Lights;
using RaytracerLib.MathLib.PolynomialFunction;
using System.Diagnostics;
using RaytracerLib.Postprocessing;
using NLog.Targets;
using RaytracerLib.Renderers;
using RaytracerLib.Cameras;
using RaytracerLib.Postprocessing.LightCorrector;
using TomanuExtensions.Utils;

namespace Raytracer
{
    public partial class RaytracerForm : Form
    {
        private Logger Logger;
        private Scene m_scene;
        private bool m_sceneModified;
        private bool m_resizing;
        private Bitmap m_bitmap;

        public RaytracerForm()
        {
            InitializeComponent();

            PropertiesManager.PropertyGrid = propertyGrid;
        }

        private void event_Form_Load(object sender, EventArgs e)
        {
            Logger = LogManager.GetLogger("MainForm");

            m_resizing = true;
            Configuration.Instance.FormState.RestoreFormState(this);
            try
            {
                splitContainer3.SplitterDistance =
                    Configuration.Instance.FormState.LogSplitterPos;
                splitContainer1.SplitterDistance =
                    Configuration.Instance.FormState.Spliter1Pos;
                splitContainer2.SplitterDistance =
                    Configuration.Instance.FormState.Spliter2Pos;
                propertyGrid.PropertySort =
                    Configuration.Instance.FormState.PropertySort;
            }
            catch
            {
                WindowState = FormWindowState.Maximized;
                splitContainer3.SplitterDistance = 656;
                Configuration.Instance.FormState.LogSplitterPos = splitContainer3.SplitterDistance;
                splitContainer1.SplitterDistance = 804;
                Configuration.Instance.FormState.Spliter1Pos = splitContainer1.SplitterDistance;
                splitContainer2.SplitterDistance = 391;
                Configuration.Instance.FormState.Spliter2Pos = splitContainer2.SplitterDistance;
                propertyGrid.PropertySort = PropertySort.Categorized;
            }

            m_resizing = false;

            renderToolStripButton.Enabled = false;
            saveImageToolStripButton.Enabled = false;
            stopRenderToolStripButton.Enabled = false;

            Configuration.Instance.LastOpenFiles.Check();

            FormsUtils.CenterControlInPanel(centerPanel);

            LoadXml(Configuration.Instance.LastOpenFiles.LastOpenFile);
        }

        private void LoadXml(string a_file)
        {
            if (String.IsNullOrWhiteSpace(a_file))
                return;

            Configuration.Instance.LastOpenFiles.Opened(a_file);
            saveAsToolStripButton.Enabled = true;
            saveToolStripButton.Enabled = false;

            try
            {
                m_scene = Scene.LoadFromFile(a_file);
                m_sceneModified = false;
            }
            catch (Exception ex)
            {
                System.Console.WriteLine(ex);
                MessageBox.Show(String.Format("Loading file {0} failed.", a_file),
                    Application.ProductName, MessageBoxButtons.OK,
                    MessageBoxIcon.Error);
                return;
            }

            renderToolStripButton.Enabled = true;
            saveImageToolStripButton.Enabled = true;
            stopRenderToolStripButton.Enabled = true;

            Text = Application.ProductName + " - " +
                Path.GetFileName(Configuration.Instance.LastOpenFiles.LastOpenFile);

            TreeManager.BuildSceneTree(m_scene, sceneTreeView);
            intersectionTreeView.Nodes.Clear();

            Stop();
            Render();
        }

        private void SceneModified()
        {
            m_sceneModified = true;
            saveToolStripButton.Enabled = true;
            Text = Application.ProductName + " - " +
                Path.GetFileName(Configuration.Instance.LastOpenFiles.LastOpenFile) + "*";
        }

        private void Render()
        {
            if (backgroundWorker.IsBusy)
                return;
            if (m_scene == null)
                return;

            RenderEvent(true);

            Scene scene = m_scene.DeepClone();

            Renderer renderer = scene.CreateRenderer();

            m_bitmap = new Bitmap(scene.ActiveCamera.Film.GetFilmRect().Width,
               scene.ActiveCamera.Film.GetFilmRect().Height);
            pictureBox.Image = new Bitmap(m_bitmap.Width, m_bitmap.Height);
            pictureBox.Size = new Size(m_bitmap.Width, m_bitmap.Height);

            backgroundWorker.RunWorkerAsync(renderer);
        }

        private void event_backgroundWorker_DoWork(object sender, DoWorkEventArgs e)
        {
            Logger.Error("Starting rendering");

            //Microsoft.VisualStudio.Profiler.DataCollection.ResumeProfile(
            //    Microsoft.VisualStudio.Profiler.ProfileLevel.Global,
            //    Microsoft.VisualStudio.Profiler.DataCollection.CurrentId);

            Renderer renderer = e.Argument as Renderer;

            renderer.ShouldStop += () => backgroundWorker.CancellationPending;

            renderer.UpdateCallback += () =>
            {
                Invoke(new Action(() =>
                {
                    renderer.UpdateBitmap(m_bitmap);
                    RedrawScene();
                }));
            };

            renderer.Render();

            //Microsoft.VisualStudio.Profiler.DataCollection.SuspendProfile(
            //    Microsoft.VisualStudio.Profiler.ProfileLevel.Global,
            //    Microsoft.VisualStudio.Profiler.DataCollection.CurrentId);

            e.Result = renderer.Scene.Statistics;

            if (backgroundWorker.CancellationPending)
                e.Cancel = true;
        }

        private void RedrawScene()
        {
            if (m_scene == null)
                return;

            using (Graphics g = Graphics.FromImage(pictureBox.Image))
                g.DrawImage(m_bitmap, 0, 0);

            pictureBox.Refresh();
        }

        private void event_backgroundWorker_RunWorkerCompleted(object sender,
            RunWorkerCompletedEventArgs e)
        {
            RenderEvent(false);
            RedrawScene();

            m_bitmap = null;
            GC.Collect();

            if (e.Error != null)
            {
                Logger.Error(e.Error);
            }
            else if (!e.Cancelled)
            {
                Statistics s = e.Result as Statistics;
                Logger.Info("\n" + s.Report());
                Logger.Error("Rendering ended");
            }
            else
                Logger.Error("Rendering interrupted");
        }

        private void event_renderToolStripButton_Click(object sender, EventArgs e)
        {
            Render();
        }

        private void event_stopRenderToolStripButton_Click(object sender, EventArgs e)
        {
            Stop(false);
        }

        private void event_OnLastOpenItemClick(object sender, EventArgs e)
        {
            ToolStripDropDownItem dd = sender as ToolStripDropDownItem;

            LoadXml(dd.Text);
        }

        private void event_toolStripDropDownButton1_DropDownOpening(object sender,
            EventArgs e)
        {
            Configuration.Instance.LastOpenFiles.Check();

            ToolStripDropDownButton dd = sender as ToolStripDropDownButton;
            dd.DropDown.Items.Clear();

            foreach (string s in Configuration.Instance.LastOpenFiles.RecentFiles)
            {
                ToolStripItem tti = dd.DropDown.Items.Add(s);
                tti.Click += new EventHandler(event_OnLastOpenItemClick);
            }
        }

        private void event_saveImageToolStripButton_Click(object sender, EventArgs e)
        {
            Configuration.Instance.LastOpenFiles.Check();

            saveImageFileDialog.InitialDirectory =
                Configuration.Instance.LastOpenFiles.ImageLastOpenDir;
            saveImageFileDialog.FileName = "";

            if (saveImageFileDialog.ShowDialog() == DialogResult.OK)
                SaveImage(saveImageFileDialog.FileName);
        }

        private void RenderEvent(bool a_starting)
        {
            renderToolStripButton.Enabled = !a_starting;
            stopRenderToolStripButton.Enabled = a_starting;
            saveImageToolStripButton.Enabled = !a_starting;
        }

        private void SaveImage(string a_fileName)
        {
            using (Bitmap bmp = new Bitmap(pictureBox.Image))
            {
                bmp.Save(a_fileName, System.Drawing.Imaging.ImageFormat.Png);
            }
        }

        private void event_saveToolStripButton_Click(object sender, EventArgs e)
        {
            SaveXml(a_showDialog: false);
        }

        private bool SaveXml(bool a_showDialog = false)
        {
            Configuration.Instance.LastOpenFiles.Check();

            if (Configuration.Instance.LastOpenFiles.LastOpenFile == "")
                a_showDialog = true;

            saveFileDialog.FileName = Configuration.Instance.LastOpenFiles.LastOpenFile;

            if (a_showDialog)
            {
                saveFileDialog.InitialDirectory =
                    Configuration.Instance.LastOpenFiles.LastOpenDir;
                saveFileDialog.FileName = Path.GetFileName(
                    Configuration.Instance.LastOpenFiles.LastOpenFile);

                if (saveFileDialog.ShowDialog() != DialogResult.OK)
                    return false;
            }

            m_scene.SaveToFile(saveFileDialog.FileName);
            Configuration.Instance.LastOpenFiles.Opened(saveFileDialog.FileName);

            Text = Application.ProductName + " - " +
                Path.GetFileName(Configuration.Instance.LastOpenFiles.LastOpenFile);
            m_sceneModified = false;
            saveToolStripButton.Enabled = false;

            return true;
        }

        private void event_Form_FormClosed(object sender, FormClosedEventArgs e)
        {
            Stop();

            Debug.Assert(LogManager.Configuration.RemoveTarget("richTextBox"));

            Configuration.Instance.FormState.SaveFormState(this);
        }

        private void Stop(bool a_wait = true)
        {
            backgroundWorker.CancelAsync();

            if (a_wait)
            {
                while (backgroundWorker.IsBusy)
                {
                    System.Threading.Thread.Sleep(100);
                    Application.DoEvents();
                }
            }
        }

        private void event_openToolStripSplitButton_DropDownOpening(object sender,
            EventArgs e)
        {
            Configuration.Instance.LastOpenFiles.Check();

            ToolStripSplitButton sb = sender as ToolStripSplitButton;
            sb.DropDown.Items.Clear();

            foreach (string s in Configuration.Instance.LastOpenFiles.RecentFiles)
            {
                ToolStripItem tti = sb.DropDown.Items.Add(s);
                tti.Click += new EventHandler(event_OnLastOpenItemClick);
            }
        }

        private void event_openToolStripSplitButton_ButtonClick(object sender,
            EventArgs e)
        {
            Configuration.Instance.LastOpenFiles.Check();

            openFileDialog.InitialDirectory =
                Configuration.Instance.LastOpenFiles.LastOpenDir;
            openFileDialog.FileName = "";

            if (!SaveChanges(MessageBoxButtons.YesNo))
                return;

            if (openFileDialog.ShowDialog() == DialogResult.OK)
                LoadXml(openFileDialog.FileName);
        }

        private void event_Form_FormClosing(object sender, FormClosingEventArgs e)
        {
            e.Cancel = !SaveChanges();
        }

        private bool SaveChanges(MessageBoxButtons a_buttons =
            MessageBoxButtons.YesNoCancel)
        {
            if (m_sceneModified)
            {
                var res = MessageBox.Show("Save changes ?", Application.ProductName,
                    a_buttons, MessageBoxIcon.Question);

                if (res == DialogResult.Yes)
                {
                    if (!SaveXml())
                        return false;
                }
                else if (res == System.Windows.Forms.DialogResult.Cancel)
                    return false;
            }

            return true;
        }

        private void event_saveAsToolStripButton_Click(object sender, EventArgs e)
        {
            SaveXml(a_showDialog: true);
        }

        private void event_generatorToolStripButton_Click(object sender, EventArgs e)
        {
            new GeneratorForm().ShowDialog();
        }

        private void event_splitContainer3_SplitterMoved(object sender, SplitterEventArgs e)
        {
            if (!m_resizing)
            {
                Configuration.Instance.FormState.LogSplitterPos =
                    splitContainer3.SplitterDistance;
            }
        }

        private void event_splitContainer1_SplitterMoved(object sender, SplitterEventArgs e)
        {
            if (!m_resizing)
            {
                Configuration.Instance.FormState.Spliter1Pos =
                    splitContainer1.SplitterDistance;
            }
        }

        private void event_splitContainer2_SplitterMoved(object sender, SplitterEventArgs e)
        {
            if (!m_resizing)
            {
                Configuration.Instance.FormState.Spliter2Pos =
                    splitContainer2.SplitterDistance;
            }
        }

        private void event_propertyGrid_PropertySortChanged(object sender, EventArgs e)
        {
            if (!m_resizing)
                Configuration.Instance.FormState.PropertySort = propertyGrid.PropertySort;
        }

        private void event_RaytracerForm_Resize(object sender, EventArgs e)
        {
            if (!m_resizing)
                Configuration.Instance.FormState.SaveFormState(this);
        }

        private void event_sceneTreeView_AfterSelect(object sender, TreeViewEventArgs e)
        {
            PropertiesManager.Update(
                (sceneTreeView.SelectedNode == null) ? null : sceneTreeView.SelectedNode.Tag);
        }

        private void event_propertyGrid_PropertyValueChanged(object s,
            PropertyValueChangedEventArgs e)
        {
            propertyGrid.Refresh();
            TreeManager.RefreshSceneTree(m_scene, sceneTreeView);
            SceneModified();
        }

        private void event_pictureBox_MouseMove(object sender, MouseEventArgs e)
        {
            mousePosToolStripStatusLabel.Text = String.Format("X: {0}, Y: {1}", e.X, e.Y);
        }

        private void event_pictureBox_MouseUp(object sender, MouseEventArgs e)
        {
            if (m_scene == null)
                return;

            if (e.Button.HasFlag(MouseButtons.Right))
            {
                Renderer renderer = m_scene.DeepClone().CreateRenderer();
                Intersection intersection = renderer.RenderTestPixel(e.X, e.Y);
                TreeManager.BuildIntersectionTree(intersection, intersectionTreeView);
                tabControl.SelectTab(1);
            }
        }

        private void testToolStripButton_Click(object sender, EventArgs e)
        {
            new Tester.TesterForm().ShowDialog();
        }

        private void event_RaytracerForm_LocationChanged(object sender, EventArgs e)
        {
            if (!m_resizing)
                Configuration.Instance.FormState.SaveFormState(this);
        }

        private void event_intersectionTreeView_AfterSelect(object sender, TreeViewEventArgs e)
        {
             PropertiesManager.Update(
                (intersectionTreeView.SelectedNode == null) ? null : 
                intersectionTreeView.SelectedNode.Tag);
        }

        private void tabControl_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (tabControl.SelectedIndex == 0)
            {
                var temp = sceneTreeView.SelectedNode;
                sceneTreeView.SelectedNode = null;
                sceneTreeView.SelectedNode = temp;
            }
            else if (tabControl.SelectedIndex == 2)
            {
                var temp = intersectionTreeView.SelectedNode;
                intersectionTreeView.SelectedNode = null;
                intersectionTreeView.SelectedNode = temp;
            }
        }

        private void event_sceneTreeView_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Delete)
            {
                if (sceneTreeView.SelectedNode != null)
                {
                    if (sceneTreeView.SelectedNode.Tag != null)
                    {
                        if (sceneTreeView.SelectedNode.Tag is Material)
                        {
                            m_scene.Materials.Remove(sceneTreeView.SelectedNode.Tag as Material);
                            sceneTreeView.SelectedNode.Remove();

                            SceneModified();
                            TreeManager.RefreshSceneTree(m_scene, sceneTreeView);
                        }
                        else if (sceneTreeView.SelectedNode.Tag is RenderableObject)
                        {
                            m_scene.RenderableObjects.Remove(sceneTreeView.SelectedNode.Tag as RenderableObject);
                            sceneTreeView.SelectedNode.Remove();

                            SceneModified();
                            TreeManager.RefreshSceneTree(m_scene, sceneTreeView);
                        }
                        else if (sceneTreeView.SelectedNode.Tag is Light)
                        {
                            m_scene.Lights.Remove(sceneTreeView.SelectedNode.Tag as Light);
                            sceneTreeView.SelectedNode.Remove();

                            SceneModified();
                            TreeManager.RefreshSceneTree(m_scene, sceneTreeView);
                        }
                        else if (sceneTreeView.SelectedNode.Tag is Camera)
                        {
                            if (sceneTreeView.SelectedNode.Parent.Tag is CamerasList)
                            {
                                m_scene.Cameras.Remove(sceneTreeView.SelectedNode.Tag as Camera);
                                sceneTreeView.SelectedNode.Remove();

                                SceneModified();
                                TreeManager.RefreshSceneTree(m_scene, sceneTreeView);
                            }
                        }
                        else if (sceneTreeView.SelectedNode.Tag is Postprocessor)
                        {
                            Film film = sceneTreeView.SelectedNode.Parent.Parent.Tag as Film;
                            film.Postprocessors.Remove(sceneTreeView.SelectedNode.Tag as Postprocessor);
                            var parent = sceneTreeView.SelectedNode.Parent;
                            sceneTreeView.SelectedNode.Remove();

                            if (!film.Postprocessors.Any())
                                parent.Remove();  
                            
                            SceneModified();
                            TreeManager.RefreshSceneTree(m_scene, sceneTreeView);
                        }
                        else if (sceneTreeView.SelectedNode.Tag is Film)
                        {
                            Film film = sceneTreeView.SelectedNode.Tag as Film;
                            if (!Object.ReferenceEquals(m_scene.ActiveCamera.Film, film))
                            {
                                m_scene.Films.Remove(film);
                                sceneTreeView.SelectedNode.Remove();

                                SceneModified();
                                TreeManager.RefreshSceneTree(m_scene, sceneTreeView);
                            }
                        }
                    }
                    else
                    {
                        if (sceneTreeView.SelectedNode.Parent.Tag is Material)
                        {
                            (sceneTreeView.SelectedNode.Parent.Tag as Material).ReplaceMaterialPart(
                                sceneTreeView.SelectedNode.Nodes[0].Tag as IMaterialPart, null);
                            sceneTreeView.SelectedNode.Remove();

                            SceneModified();
                            TreeManager.RefreshSceneTree(m_scene, sceneTreeView);
                        }
                    }
                }
            }
        }

        private void sceneTreeView_MouseUp(object sender, MouseEventArgs e)
        {
            if (e.Button != MouseButtons.Right)
                return;
            if (sceneTreeView.SelectedNode == null)
                return;

            object obj = sceneTreeView.SelectedNode.Tag;

            if (obj is CamerasList)
            {
                ContextMenu menu = new ContextMenu();

                {
                    MenuItem add = new MenuItem("Add perpective camera");
                    add.Click += (ss, ee) =>
                    {
                        Camera camera = new PerspectiveCamera(Vector3.XAXIS, Vector3.YAXIS);
                        (obj as CamerasList).Add(camera);

                        TreeManager.AddItem(sceneTreeView.SelectedNode, camera);

                        SceneModified();
                        TreeManager.RefreshSceneTree(m_scene, sceneTreeView);
                    };
                    menu.MenuItems.Add(add);
                }

                menu.Show(sceneTreeView, e.Location);
            }
            else if (obj is Camera)
            {
                if (sceneTreeView.SelectedNode.Parent.Tag is CamerasList)
                {
                    ContextMenu menu = new ContextMenu();

                    {
                        MenuItem add = new MenuItem("Add perpective camera");
                        add.Click += (ss, ee) =>
                        {
                            Camera camera = new PerspectiveCamera(Vector3.XAXIS, Vector3.YAXIS);
                            (sceneTreeView.SelectedNode.Parent.Tag as CamerasList).Add(camera);

                            TreeManager.InsertAfterItem(sceneTreeView.SelectedNode, camera);

                            SceneModified();
                            TreeManager.RefreshSceneTree(m_scene, sceneTreeView);
                        };
                        menu.MenuItems.Add(add);
                    }

                    {
                        MenuItem delete = new MenuItem("Delete camera");
                        delete.Click += (ss, ee) =>
                        {
                            (obj as Camera).Remove();

                            SceneModified();
                            TreeManager.RefreshSceneTree(m_scene, sceneTreeView);
                        };
                        menu.MenuItems.Add(delete);
                    }

                    menu.Show(sceneTreeView, e.Location);
                }
            }
            else if (obj is PostprocessorsList)
            {
                ContextMenu menu = new ContextMenu();

                Action<Postprocessor> add_action = (post) =>
                {
                    (obj as PostprocessorsList).Add(post);

                    TreeManager.AddItem(sceneTreeView.SelectedNode, post);

                    SceneModified();
                    TreeManager.RefreshSceneTree(m_scene, sceneTreeView);
                };

                AddPostprocessorsToMenu(menu, add_action);

                menu.Show(sceneTreeView, e.Location);
            }
            else if (obj is Postprocessor)
            {
                ContextMenu menu = new ContextMenu();

                Action<Postprocessor> add_action = (post) =>
                {
                    (sceneTreeView.SelectedNode.Parent.Tag as PostprocessorsList).Add(post);

                    TreeManager.InsertAfterItem(sceneTreeView.SelectedNode, post);

                    SceneModified();
                    TreeManager.RefreshSceneTree(m_scene, sceneTreeView);
                };

                AddPostprocessorsToMenu(menu, add_action);

                {
                    MenuItem delete = new MenuItem("Delete postprocessor");
                    delete.Click += (ss, ee) =>
                    {
                        (sceneTreeView.SelectedNode.Parent.Tag as PostprocessorsList).Remove(obj as Postprocessor);

                        var post_list = sceneTreeView.SelectedNode.Parent;
                        sceneTreeView.SelectedNode.Remove();
                        if (post_list.Nodes.Count == 0)
                            post_list.Remove();

                        SceneModified();
                        TreeManager.RefreshSceneTree(m_scene, sceneTreeView);
                    };
                    menu.MenuItems.Add(delete);
                }

                menu.Show(sceneTreeView, e.Location);

                menu.Show(sceneTreeView, e.Location);
            }
            else if (obj is Film)
            {
                ContextMenu menu = new ContextMenu();

                Action<Postprocessor> add_action = (post) =>
                {
                    if (!(obj as Film).Postprocessors.Any())
                    {
                        var pn = sceneTreeView.SelectedNode.Nodes.Add("Postprocessors");
                        pn.Tag = (obj as Film).Postprocessors;
                    }

                    var post_list = sceneTreeView.SelectedNode.Nodes[0];

                    (obj as Film).Postprocessors.Add(post);

                    TreeManager.AddItem(post_list, post);

                    SceneModified();
                    TreeManager.RefreshSceneTree(m_scene, sceneTreeView);
                };

                AddPostprocessorsToMenu(menu, add_action);

                menu.Show(sceneTreeView, e.Location);
            }
        }

        private void AddPostprocessorsToMenu(ContextMenu a_menu, Action<Postprocessor> a_add_action)
        {
            {
                MenuItem add = new MenuItem("Add Clip Each Pixel Tone Mapper");
                add.Click += (ss, ee) => a_add_action(new ClipEachPixelToneMapper());
                a_menu.MenuItems.Add(add);
            }

            {
                MenuItem add = new MenuItem("Add Global Tone Mapper");
                add.Click += (ss, ee) => a_add_action(new GlobalToneMapper());
                a_menu.MenuItems.Add(add);
            }

            {
                MenuItem add = new MenuItem("Add Scale All Linear Tone Mapper");
                add.Click += (ss, ee) => a_add_action(new ScaleAllLinearToneMapper());
                a_menu.MenuItems.Add(add);
            }

            {
                MenuItem add = new MenuItem("Add Scale Each Pixel Tone Mapper");
                add.Click += (ss, ee) => a_add_action(new ScaleEachPixelToneMapper());
                a_menu.MenuItems.Add(add);
            }

            {
                MenuItem add = new MenuItem("Add Gamma Corrector");
                add.Click += (ss, ee) => a_add_action(new GammaCorrector());
                a_menu.MenuItems.Add(add);
            }

            {
                MenuItem add = new MenuItem("Add Gamma Linear To SRGB");
                add.Click += (ss, ee) => a_add_action(new GammaLinearToSRGB());
                a_menu.MenuItems.Add(add);
            }

            {
                MenuItem add = new MenuItem("Add Gamma SRGB To Linear");
                add.Click += (ss, ee) => a_add_action(new GammaSRGBtoLinear());
                a_menu.MenuItems.Add(add);
            }

            {
                MenuItem add = new MenuItem("Add Twist Effect");
                add.Click += (ss, ee) => a_add_action(new TwistEffect());
                a_menu.MenuItems.Add(add);
            }
        }

        private void sceneTreeView_MouseDown(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Right)
                sceneTreeView.SelectedNode = sceneTreeView.GetNodeAt(e.Location);
        }

        private void clearLogToolStripMenuItem_Click(object sender, EventArgs e)
        {
            (LogManager.Configuration.FindTargetByName("richTextBox") as RichTextBoxTarget).Clear();
        }
    }
}